/*
 * ResourceFilter.java
 *
 * Created on 2 2007, 2:21
 */

package server.filters;

import java.io.*;
import java.net.*;
import java.text.*;
import javax.servlet.*;
import javax.servlet.http.*;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.apache.log4j.Logger;
import server.utils.ResourceManager;

/**
 *
 * @author  alexog
 * @version
 */

public class ResourceFilter implements Filter {
    
    private FilterConfig filterConfig = null;
    
    private static Logger log = null;
    
    private ServletContext ctx;
    
    static {
        log = Logger.getLogger(server.filters.ResourceFilter.class);
    }
    
    public ResourceFilter() {
    }
    
    private void doBeforeProcessing(ServletRequest servletRequest, ServletResponse servletResponse)
    throws IOException, ServletException {
        // Initialize the context if required
        if (ctx == null) {
            ctx = filterConfig.getServletContext();
        }
        // process the request
        if (servletRequest instanceof HttpServletRequest) {
            HttpServletRequest request = (HttpServletRequest) servletRequest;
            HttpServletResponse response = (HttpServletResponse) servletResponse;
            if (ResourceManager.isResourceRequest(request)){
                InputStream resourceStream;
                boolean localized = false;
                resourceStream = ResourceManager.getStaticResourceAsStream(request,localized);
                if (resourceStream != null){
                    //log.debug("Found requested resource: " + request.getRequestURI());
                    byte[] buff = new byte[256];
                    int nbBytes = 0;
                    while ((nbBytes = resourceStream.read(buff)) != -1){
                        servletResponse.getOutputStream().write(buff,0,nbBytes);
                    }
                    resourceStream.close();
                    servletResponse.flushBuffer();
                } else {
                    log.warn("Could not find requested resource: " + request.getRequestURI());
                    response.setStatus(HttpServletResponse.SC_NOT_FOUND);
                }
                
            }
        }
    }
    
    private void doAfterProcessing(ServletRequest request, ServletResponse response)
    throws IOException, ServletException {
    }
    
    /**
     *
     * @param request The servlet request we are processing
     * @param result The servlet response we are creating
     * @param chain The filter chain we are processing
     *
     * @exception IOException if an input/output error occurs
     * @exception ServletException if a servlet error occurs
     */
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain)
            throws IOException, ServletException {
        
        log.info("ResourceFilter:doFilter()");
        
        doBeforeProcessing(request, response);
        
        Throwable problem = null;
        
        try {
            chain.doFilter(request, response);
        } catch(Throwable t) {
            problem = t;
            t.printStackTrace();
        }
        
        doAfterProcessing(request, response);
        
        if (problem != null) {
            if (problem instanceof ServletException) throw (ServletException)problem;
            if (problem instanceof IOException) throw (IOException)problem;
            sendProcessingError(problem, response);
        }
    }
    
    
    /**
     * Return the filter configuration object for this filter.
     */
    public FilterConfig getFilterConfig() {
        return (this.filterConfig);
    }
    
    
    /**
     * Set the filter configuration object for this filter.
     *
     * @param filterConfig The filter configuration object
     */
    public void setFilterConfig(FilterConfig filterConfig) {
        
        this.filterConfig = filterConfig;
    }
    
    /**
     * Destroy method for this filter
     *
     */
    public void destroy() {
    }
    
    
    /**
     * Init method for this filter
     *
     */
    public void init(FilterConfig filterConfig) {
        
        this.filterConfig = filterConfig;
        if (filterConfig != null) {
            log.info("ResourceFilter:Initializing filter");
        }
    }
    
    /**
     * Return a String representation of this object.
     */
    public String toString() {
        
        if (filterConfig == null) return (this.getClass().getName()+"()");
        StringBuffer sb = new StringBuffer(this.getClass().getName()+"ResourceFilter(");
        sb.append(filterConfig);
        sb.append(")");
        return (sb.toString());
        
    }
    
    private void sendProcessingError(Throwable t, ServletResponse response) {
        
        String stackTrace = getStackTrace(t);
        log.error(stackTrace);
        if(stackTrace != null && !stackTrace.equals("")) {
            
        } else {
            //TODO: Redirect to error Page
        }
    }
    
    public static String getStackTrace(Throwable t) {
        
        String stackTrace = null;
        
        try {
            StringWriter sw = new StringWriter();
            PrintWriter pw = new PrintWriter(sw);
            t.printStackTrace(pw);
            pw.close();
            sw.close();
            stackTrace = sw.getBuffer().toString();
        } catch(Exception ex) {}
        return stackTrace;
    }
}
